﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Xml.Serialization;

namespace BDSim
{
    /// <summary>
    ///UTC形式的时间结构  
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct UTCTime
    {
        [XmlAttribute]
        public int Year;

        [XmlAttribute]
        public int Mon;

        [XmlAttribute]
        public int Day;

        [XmlAttribute]
        public int Hour;

        [XmlAttribute]
        public int Min;

        [XmlAttribute]
        public double Sec;

        [XmlAttribute]
        public double JD;

        /// <summary>
        /// JD的整数部分
        /// </summary>
        [XmlAttribute]
        public double IntJD;

        /// <summary>
        /// JD的小数部分
        /// </summary>
        [XmlAttribute]
        public double DouJD;

        [XmlIgnore]
        public int year { get { return Year; } set { Year = value; } }

        [XmlIgnore]
        public int mon { get { return Mon; } set { Mon = value; } }

        [XmlIgnore]
        public int day { get { return Day; } set { Day = value; } }

        [XmlIgnore]
        public int hour { get { return Hour; } set { Hour = value; } }

        [XmlIgnore]
        public int min { get { return Min; } set { Min = value; } }

        [XmlIgnore]
        public double sec
        {
            get
            {
                if (Sec < 0)
                    return 0;
                else
                    return Sec;
            }
            set
            {
                if (value >= 0)
                    Sec = value;
            }
        }

        [XmlIgnore]
        public double Jd { get { return JD; } set { JD = value; } }

        [XmlIgnore]
        public double intJd { get { return IntJD; } set { IntJD = value; } }

        [XmlIgnore]
        public double douJd { get { return DouJD; } set { DouJD = value; } }

        /// <summary>
        /// 默认值 
        /// </summary>
        [XmlIgnore]
        public static UTCTime Default { get { return new UTCTime(2014, 10, 1, 12, 0, 0, 2456932.0); } }

        public UTCTime(int Iy, int Im, int Id, int Ih, int Imin, double Is, double iJD)
        {
            Year = Iy;
            Mon = Im;
            Day = Id;
            Hour = Ih;
            Min = Imin;
            Sec = Is;
            JD = iJD;
            IntJD = (int)iJD;
            DouJD = JD - IntJD;
        }

        public override string ToString()
        {
            string str = string.Format("{0}-{1}-{2} {3}:{4}:{5}", Year.ToString("0000"), Mon.ToString("00"), Day.ToString("00"), Hour.ToString("00"), Min.ToString("00"), Math.Round(Sec, 1).ToString("00"));
            return str;
        }

        public string ToFileName()
        {
            return string.Format("{0}_{1}_{2}_{3}_{4}_{5}", Year.ToString("0000"), Mon.ToString("00"), Day.ToString("00"), Hour.ToString("00"), Min.ToString("00"), Math.Round(Sec, 1).ToString("00"));
        }

        public DateTime ToDateTime()
        {
            if (Sec < 0)
            {
                Sec = 0;
            }
            DateTime dateTime = new DateTime(year, mon, day, Hour, min, (int)Sec);
            dateTime = dateTime.AddMilliseconds((Sec - (int)Sec) * 1000);
            return dateTime;
        }

        // add by liuy on 2016 7 14
        public static UTCTime FromDateTime(DateTime dateTime)
        {
            UTCTime utc = new UTCTime();
            utc.year = dateTime.Year;
            utc.mon = dateTime.Month;
            utc.day = dateTime.Day;
            utc.hour = dateTime.Hour;
            utc.min = dateTime.Minute;
            utc.sec = dateTime.Second + dateTime.Millisecond / 1000.0;
            return utc;
        }

        public void LoadFromDateTime(DateTime dateTime)
        {
            this.year = dateTime.Year;
            this.mon = dateTime.Month;
            this.day = dateTime.Day;
            this.hour = dateTime.Hour;
            this.min = dateTime.Minute;
            this.sec = dateTime.Second + dateTime.Millisecond / 1000.0;
        }

        // add by liuy on 2016 7 18
        public int CompareTo(UTCTime utc)
        {
            DateTime dateTimeThis = this.ToDateTime();
            DateTime dateTimeUtc = utc.ToDateTime();
            return dateTimeThis.CompareTo(dateTimeUtc);
        }

        public void AddSecond(double seconds)
        {
            DateTime temp = this.ToDateTime();
            temp = temp.AddMilliseconds(seconds * 1000);
            this.LoadFromDateTime(temp);
        }

        public string ToSTKTime()
        {
            string result = "";
            Dictionary<int, string> MonthDic = new Dictionary<int, string>() { { 1, "Jan" }, { 2, "Feb" }, { 3, "Mar" }, { 4, "Apr" } 
            ,{5,"May"},{6,"Jun"},{7,"Jul"},{8,"Aug"},{9,"Sep"},{10,"Oct"},{11,"Nov"},{12,"Dec"}};
            result = string.Format("{0} {1} {2} {3}:{4}:{5}", day, MonthDic[mon], year, hour, min, sec);
            return result;
        }

        public UTCTimeClass ToUTCTimeClass()
        {
            UTCTimeClass utc_c = new UTCTimeClass();
            utc_c.year = this.year;
            utc_c.mon = this.mon;
            utc_c.day = this.day;
            utc_c.hour = this.hour;
            utc_c.min = this.min;
            utc_c.sec = this.sec;
            utc_c.Jd = this.Jd;
            utc_c.intJd = this.intJd;
            utc_c.douJd = this.douJd;
            return utc_c;
        }

    };

    /// <summary>
    /// UTC形式的时间结构类，用于界面属性设置
    /// </summary>
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class UTCTimeClass: PropertyNotify
    {
        [XmlAttribute]
        public int Year = 2015;

        [XmlAttribute]
        public int Mon = 10;

        [XmlAttribute]
        public int Day = 1;

        [XmlAttribute]
        public int Hour = 12;

        [XmlAttribute]
        public int Min = 0;

        [XmlAttribute]
        public double Sec = 0;

        [XmlAttribute]
        public double JD = 2457297;

        /// <summary>
        /// JD的小数部分
        /// </summary>
        [XmlAttribute]
        public double IntJD = 2457297;

        /// <summary>
        /// JD的整数部分
        /// </summary>
        [XmlAttribute]
        public double DouJD = 0;

        [XmlIgnore, ReadOnly(true), DisplayName("Year"), PropertyOrder(1)]
        public int year
        {
            get { return Year; }
            set
            {
                DateTime dateTime;
                if (DateTime.TryParse(string.Format("{0}-{1}-{2} {3}:{4}:{5}", value, Mon, Day, Hour, Min, Sec), out dateTime))
                {
                    Year = value;
                }
                NotifyPropertyChanged("year");
            }
        }

        [XmlIgnore, ReadOnly(true), DisplayName("Mon"), PropertyOrder(2)]
        public int mon
        {
            get { return Mon; }
            set
            {
                DateTime dateTime;
                if (DateTime.TryParse(string.Format("{0}-{1}-{2} {3}:{4}:{5}", Year, value, Day, Hour, Min, Sec), out dateTime))
                {
                    Mon = value;
                }
                NotifyPropertyChanged("mon");
            }
        }

        [XmlIgnore, ReadOnly(true), DisplayName("Day"), PropertyOrder(3)]
        public int day
        {
            get { return Day; }
            set
            {
                DateTime dateTime;
                if (DateTime.TryParse(string.Format("{0}-{1}-{2} {3}:{4}:{5}", Year, Mon, value, Hour, Min, Sec), out dateTime))
                {
                    Day = value;
                }
                NotifyPropertyChanged("day");
            }
        }

        [XmlIgnore, ReadOnly(true), DisplayName("Hour"), PropertyOrder(4)]
        public int hour
        {
            get { return Hour; }
            set
            {
                DateTime dateTime;
                if (DateTime.TryParse(string.Format("{0}-{1}-{2} {3}:{4}:{5}", Year, Mon, Day, value, Min, Sec), out dateTime))
                {
                    Hour = value;
                }
                NotifyPropertyChanged("hour");
            }
        }

        [XmlIgnore, ReadOnly(true), DisplayName("Min"), PropertyOrder(5)]
        public int min
        {
            get { return Min; }
            set
            {
                DateTime dateTime;
                if (DateTime.TryParse(string.Format("{0}-{1}-{2} {3}:{4}:{5}", Year, Mon, Day, Hour, value, Sec), out dateTime))
                {
                    Min = value;
                }
                NotifyPropertyChanged("min");
            }
        }

        [XmlIgnore, ReadOnly(true), DisplayName("Sec"), PropertyOrder(6)]
        public double sec
        {
            get { return Sec; }
            set
            {
                DateTime dateTime;
                if (DateTime.TryParse(string.Format("{0}-{1}-{2} {3}:{4}:{5}", Year, Mon, Day, Hour, Min, value), out dateTime))
                {
                    Sec = value;
                }
                NotifyPropertyChanged("sec");
            }
        }

        [XmlIgnore, Browsable(false), DisplayName("JD")]
        public double Jd { get { return JD; } set { JD = value; NotifyPropertyChanged("Jd"); } }

        [XmlIgnore, Browsable(false)]
        public double intJd { get { return IntJD; } set { IntJD = Math.Floor(JD); NotifyPropertyChanged("intJd"); } }

        [XmlIgnore, Browsable(false)]
        public double douJd { get { return DouJD; } set { DouJD = JD - Math.Floor(JD); NotifyPropertyChanged("douJd"); } }


        public override string ToString()
        {
            string str = string.Format("{0}-{1}-{2} {3}:{4}:{5}", Year.ToString(), Mon.ToString("00"), Day.ToString("00"), Hour.ToString("00"), Min.ToString("00"), Math.Round(Sec, 1).ToString("00"));
            return str;
        }

        public DateTime ToDateTime()
        {
            DateTime dateTime = new DateTime(year, mon, day, Hour, min, (int)Sec);

            return dateTime;
        }

        public void LoadFromDateTime(DateTime dateTime)
        {
            this.year = dateTime.Year;
            this.mon = dateTime.Month;
            this.day = dateTime.Day;
            this.hour = dateTime.Hour;
            this.min = dateTime.Minute;
            this.sec = dateTime.Second;
        }

        public UTCTime ToUTCTime()
        {
            UTCTime utc = new UTCTime();
            utc.year = this.year;
            utc.mon = this.mon;
            utc.day = this.day;
            utc.hour = this.hour;
            utc.min = this.min;
            utc.sec = this.sec;
            utc.Jd = this.Jd;
            utc.intJd = this.intJd;
            utc.douJd = this.douJd;
            return utc;
        }

        public UTCTimeClass()
        {
            Year = 2015;
            Mon = 10;
            Day = 1;
            Hour = 12;
            Min = 0;
            Sec = 0;
            JD = 2457297;
            IntJD = 2457297;
            DouJD = 0;
        }

        public UTCTimeClass(int Iy, int Im, int Id, int Ih, int Imin, double Is, double iJD)
        {
            Year = Iy;
            Mon = Im;
            Day = Id;
            Hour = Ih;
            Min = Imin;
            Sec = Is;
            JD = iJD;
            IntJD = (int)iJD;
            DouJD = JD - IntJD;
        }
    }


}
